package com.solr;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.params.AnalysisParams;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.taobao.tbapi.CommonUtils;

public class DefaultSolrManager<T> {

  private final static Logger log       = LoggerFactory.getLogger("solr");

  String                      serverUrl = "http://10.241.51.80:30000/solr/crmmember/";
  HttpSolrServer              server;
  HttpSolrServer              facetServer;
  Class<T>                    beanType  = null;

  public DefaultSolrManager(String serverUrl, Class<T> beanType) {
    super();
    this.serverUrl = serverUrl;
    this.beanType = beanType;
  }

  public String getServerUrl() {
    return serverUrl;
  }

  public void setServerUrl(String serverUrl) {
    this.serverUrl = serverUrl;
  }

  public void init() {

    /*
     * DefaultHttpClient httpclient = new DefaultHttpClient(); Credentials c =
     * new UsernamePasswordCredentials("hangding", "lovehangding");
     * httpclient.getCredentialsProvider().setCredentials( AuthScope.ANY, c);
     */
    server = new HttpSolrServer(serverUrl);
    server.setSoTimeout(30000); // socket read timeout
    server.setConnectionTimeout(30000);
    server.setDefaultMaxConnectionsPerHost(500);
    server.setMaxTotalConnections(1000);
    server.setFollowRedirects(false); // defaults to false
    // allowCompression defaults to false.
    // Server side must support gzip or deflate for this to have any effect.
    server.setAllowCompression(true);
    server.setMaxRetries(1); // defaults to 0. > 1 not recommended.
    HttpClientUtil.setBasicAuth((DefaultHttpClient) server.getHttpClient(), "hd", "lovehangding1314");

    facetServer = getSolrServer();
  }

  private HttpSolrServer getSolrServer() {
    HttpSolrServer server = new HttpSolrServer(serverUrl);
    server.setSoTimeout(10000); // socket read timeout
    server.setConnectionTimeout(10000);
    server.setDefaultMaxConnectionsPerHost(500);
    server.setMaxTotalConnections(1000);
    server.setFollowRedirects(false); // defaults to false
    // allowCompression defaults to false.
    // Server side must support gzip or deflate for this to have any effect.
    server.setAllowCompression(true);
    server.setMaxRetries(2); // defaults to 0. > 1 not recommended.
    HttpClientUtil.setBasicAuth((DefaultHttpClient) server.getHttpClient(), "hangding", "lovehangding");

    return server;
  }

  public QueryResponse dataImportFromDB(boolean clean, Long offset, boolean fullImport) throws SolrServerException {
    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("qt", "/dataimport");
    params.set("command", fullImport ? "full-import" : "delta-import");
    params.set("clean", clean);
    if (offset != null)
      params.set("offset", offset + "");
    QueryResponse response = server.query(params);
    return response;
  }

  public SolrResponse<T> getResultByParamsString(String fields, String queryString, String sortStr, int start, int pageSize, String... fqString)
      throws SolrServerException {
    long startT = System.currentTimeMillis();
    if (queryString == null)
      queryString = "*:*";
    SolrQuery solrQuery = new SolrQuery().setStart(start).setRows(pageSize).setQuery(queryString);
    if (fields != null)
      solrQuery.setFields(fields);
    for (String s : fqString) {
      if (s == null || s.equals(""))
        continue;
      solrQuery.addFilterQuery(s);
    }
    if (sortStr != null && !sortStr.equals("")) {
      solrQuery.set(CommonParams.SORT, sortStr);
    }
    QueryResponse rsp = null;
    try {
      rsp = server.query(solrQuery);
    } catch (SolrServerException e) {
      log.error("getResultByParamsString", e);
      throw e;
    }

    long endT = System.currentTimeMillis();
    log.warn("Solr query " + solrQuery + " cost:" + (endT - startT));
    return new SolrResponse<T>(rsp, beanType);
  }

  public QueryResponse analysis(String fieldType, String fieldValue) throws SolrServerException {
    SolrQuery query = new SolrQuery();
    query.add(CommonParams.QT, "/analysis/field"); // query type

    query.add(AnalysisParams.FIELD_VALUE, fieldValue);

    query.add(AnalysisParams.FIELD_TYPE, fieldType);
    query.add("wt", "json");

    QueryResponse rsp = null;
    try {
      rsp = server.query(query);
    } catch (SolrServerException e) {
      log.error("getResultByParamsString", e);
      throw e;
    }
    return rsp;
  }

  @SuppressWarnings("unchecked")
  public List<String> analysisChinese(String fieldValue) {
    List<String> rtn = new ArrayList<String>();

    QueryResponse response = null;
    try {
      response = this.analysis("text_zh", fieldValue);
      NamedList<Object> analysis = (NamedList<Object>) response.getResponse().get("analysis");// analysis
      // node

      NamedList<Object> field_types = (NamedList<Object>) analysis.get("field_types");// field_types
      // node

      NamedList<Object> text_chinese = (NamedList<Object>) field_types.get("text_zh");// text_chinese
      // node

      NamedList<Object> index = (NamedList<Object>) text_chinese.get("index");// index
      // node

      List<SimpleOrderedMap<String>> list = (ArrayList<SimpleOrderedMap<String>>) index.get("com.chenlb.mmseg4j.analysis.MMSegTokenizer");// tokenizer
      // node

      // 在每个词条中间加上空格，为每个词条进行或运算

      for (Iterator<SimpleOrderedMap<String>> iter = list.iterator(); iter.hasNext();)

      {

        rtn.add(iter.next().get("text"));

      }
    } catch (SolrServerException e) {
      log.error("analysisChinese", e);
      return null;
    }

    return rtn;
  }

  public QueryResponse searchWithFacet(String returnFields, int start, int pageSize, String queryString, List<String> fqs, int facetLimit, int facetOffict,
      List<String> facetFields) throws SolrServerException {

    long startT = System.currentTimeMillis();
    SolrQuery solrQuery = new SolrQuery().setStart(start).setRows(pageSize).setQuery(queryString);
    if (returnFields != null)
      solrQuery.setFields(returnFields);
    if (fqs != null) {
      for (String s : fqs) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.addFilterQuery(s);
      }
    }
    solrQuery.setFacet(true);
    solrQuery.setFacetLimit(facetLimit);
    solrQuery.setFacetSort(FacetParams.FACET_SORT_COUNT);
    solrQuery.setFacetMinCount(1);
    solrQuery.set(FacetParams.FACET_OFFSET, facetOffict);

    if (facetFields != null) {
      for (String s : facetFields) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.addFacetField(s);
      }
    }
    QueryResponse rsp = null;
    try {
      rsp = facetServer.query(solrQuery);
    } catch (SolrServerException e) {
      log.error("searchWithFacet ", e);
      throw e;
    }
    long endT = System.currentTimeMillis();
    log.warn("Solr query " + solrQuery + " cost:" + (endT - startT));

    return rsp;
  }

  public QueryResponse searchWithGroup(String returnFields, int start, int pageSize, String queryString, List<String> fqs, int groupLimit, int groupOffict,
      List<String> groupFields) throws SolrServerException {
    long startT = System.currentTimeMillis();
    SolrQuery solrQuery = new SolrQuery().setStart(start).setRows(pageSize).setQuery(queryString);
    if (returnFields != null)
      solrQuery.setFields(returnFields);
    if (fqs != null) {
      for (String s : fqs) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.addFilterQuery(s);
      }
    }
    solrQuery.set("group", "true");
    if (groupFields != null) {
      for (String s : groupFields) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.add("group.field", s);
      }
    }
    solrQuery.set("group.offset", groupOffict);
    solrQuery.set("group.limit", groupLimit);
    QueryResponse rsp = null;
    try {
      rsp = facetServer.query(solrQuery);
    } catch (SolrServerException e) {
      log.error("searchWithGroup ", e);
      throw e;
    }
    long endT = System.currentTimeMillis();
    log.warn("Solr query " + solrQuery + " cost:" + (endT - startT));
    return rsp;
  }

  public List<FacetField.Count> statisticTagByUserId(Long userId, int start, int pageSize) {
    List<String> fcs = new ArrayList<String>();

    String fc = "tags_ses";
    fcs.add(fc);
    String query = "";
    if (userId == null)
      query = "*:*";
    else
      query = "userId_l:" + userId;

    try {
      QueryResponse res = searchWithFacet(null, 0, 0, query, null, pageSize, start, fcs);
      return res.getFacetField(fc).getValues();
    } catch (SolrServerException e) {
      log.error("statisticTagByUserId", e);
      return null;
    }
  }

  public QueryResponse searchWithStats(String returnFields, int start, int pageSize, String queryString, List<String> fqs, List<String> facetFields,
      List<String> statsFields) throws SolrServerException {
    long startT = System.currentTimeMillis();
    SolrQuery solrQuery = new SolrQuery().setStart(start).setRows(pageSize).setQuery(queryString);
    if (returnFields != null)
      solrQuery.setFields(returnFields);
    if (fqs != null) {
      for (String s : fqs) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.addFilterQuery(s);
      }
    }
    solrQuery.set("stats", "true");
    if (statsFields != null) {
      for (String s : statsFields) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.add("stats.field", s);
      }
    }

    if (facetFields != null) {
      for (String s : facetFields) {
        if (s == null || s.equals(""))
          continue;
        solrQuery.add("stats.facet", s);
      }
    }
    QueryResponse rsp = null;
    try {
      rsp = facetServer.query(solrQuery);
    } catch (SolrServerException e) {
      log.error("searchWithStats ", e);
      throw e;
    }
    long endT = System.currentTimeMillis();
    log.warn("Solr query " + solrQuery + " cost:" + (endT - startT));
    return rsp;
  }

  public List<FacetField.Count> statisticTagByUserIdAndGivenTagIds(Long userId, Set<String> tagIds) {
    List<String> fcs = new ArrayList<String>();
    List<String> fqs = new ArrayList<String>();

    List<FacetField.Count> results = new ArrayList<FacetField.Count>();
    String fc = "tags_ses";
    fcs.add(fc);
    String query = "";
    if (userId == null)
      query = "*:*";
    else
      query = "userId_l:" + userId;

    String fq = fc + ":" + CommonUtils.join(tagIds, ";");
    fqs.add(fq);

    QueryResponse res = null;
    int pageSize = 1000;
    int start = 0;
    try {

      do {
        res = searchWithFacet(null, 0, 0, query, fqs, pageSize, start, fcs);
        if (res.getFacetField(fc).getValues() == null)
          break;

        for (FacetField.Count count : res.getFacetField(fc).getValues()) {
          if (tagIds.contains(count.getName())) {
            results.add(count);
          }
        }
        if (results.size() == tagIds.size())
          return results;
        start = start + pageSize;
      } while (res != null && res.getFacetField(fc) != null && res.getFacetField(fc).getValueCount() > 0);

    } catch (SolrServerException e) {
      log.error("statisticTagByUserId", e);
      return null;
    }
    return results;
  }

  public static void main(String[] args) throws SolrServerException, IOException {

  }
}
